<?php
/**
 *  微信基础控制器
 */

namespace Apps\Common\Controller;

use Deyi\Functions\HttpFunction;
use Deyi\Functions\UtilFunction;

/**
 * Class WeixinBaseController
 * @package Apps\Common\Controller
 */
class WeixinBaseController extends BaseController
{
    // 微信用户session key
    const WX_SESSION_KEY = 'wx_sess_key_new';

    // 微信授权访问地址
    const WX_AUTHORIZE_URL = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_userinfo&state=%s#wechat_redirect';

    // 微信token获取地址
    const WX_ACCESS_TOKEN_URL = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code';

    // 微信用户数据获取地址
    const WX_USERINFO_URL = 'https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN';

    // 微信访问地址cookie记录
    const WX_VISIT_URL_COOKIE_KEY = 'visit';

    protected static $wxUserInfo = null;

    protected static $isInWechat = true;

    protected $uid = 0;

    public function initialize()
    {
        parent::initialize();

        $this->view->enable();

        // 如果不是微信客戶端就不判断权限
        if (!strpos($this->request->getUserAgent(), 'MicroMessenger')) {
            static::$isInWechat = false;
            $this->uid = 1;
            return;
        }

        static::$wxUserInfo = $this->session->get(self::WX_SESSION_KEY);

        if (!static::$wxUserInfo && !in_array(static::$reqControllerName . '/' . static::$reqActionName, ['callback/notify'])) {
            if ($this->request->isAjax()) {
                static::errorThrow('尚未登录!请刷新页面重新登录!');
            } else {
                $this->cookies->set(self::WX_VISIT_URL_COOKIE_KEY, $this->request->getURI());
                $this->redirectToUrl(sprintf(
                    self::WX_AUTHORIZE_URL,
                    static::$_config->weixin->appid,
                    static::$_config->weixin->redirecturi,
                    bin2hex(UtilFunction::encryptBase64(time()))
                ));
            }
        }

        if (isset(static::$wxUserInfo->uid)) {
            $this->uid = static::$wxUserInfo->uid;
        } else {
            $this->uid = 0;
        }
    }

    public function getWeixinUserInfo($code)
    {
        $openId = '';
        $accessToken = '';
        // 接口重试3次
        for ($i = 0; $i < 3; $i++) {
            $ret = HttpFunction::getPage(sprintf(
                self::WX_ACCESS_TOKEN_URL,
                static::$_config->weixin->appid,
                static::$_config->weixin->appsecret,
                $code
            ), 3, false);
            static::$_logger->info('weixin api accesstoken result: ' . $ret . ' code: ' . $code);
            if (!$ret || !($json = json_decode($ret)) || !isset($json->access_token)) {
                continue;
            }

            $accessToken = $json->access_token;
            $openId = $json->openid;
            break;
        }

        if (empty($openId) || empty($accessToken)) {
            return false;
        }

        $json = false;
        //用户信息获取接口重试３次
        for ($i = 0; $i < 3; $i++) {
            $ret = HttpFunction::getPage(sprintf(
                self::WX_USERINFO_URL,
                $accessToken,
                $openId
            ), 3, false);

            static::$_logger->info('weixin api userinfo result: ' . $ret . ' code: ' . $code);
            if (!$ret || !($json = json_decode($ret)) || !isset($json->unionid)) {
                continue;
            }

            break;
        }

        return $json;
    }

    protected function verifyWeixinLogin()
    {
        if (!static::$wxUserInfo || !isset(static::$wxUserInfo->unionid)) {
            static::errorThrow('登录状态非法<br>请在微信端打开');
        }

        return static::$wxUserInfo;
    }
    
    /**
     * 写入微信jssdk相关数据到模板变量中
     * @version APP 6.3.5
     */
    protected function setWeixinJsContextData()
    {
        $timestamp = time();
        $nonceStr = md5(UtilFunction::getRandomString(6));

        $this->view->setVars([
            'wxjs_appid' => static::$_config->weixin->appid,
            'wxjs_noncestr' => $nonceStr,
            'wxjs_timestamp' => $timestamp,
            'wxjs_signature' => $this->getWeixinJsApiSign($nonceStr, $timestamp)
        ]);
    }

}